<?php
/**
 * 
 * @author: liwei
 */
namespace Minicli;

use think\facade\Db;

class App
{
    protected $printer;

    protected $command_registry;

    protected $app_signature;

    protected $config;

    public function __construct()
    {
        // 打印外包
        $this->printer = new CliPrinter();
        // 命令注册外包
        $this->command_registry = new CommandRegistry();
        // 获取所有的配置文件
        $this->config = new Config();
        // 对数据库进行设置
        Db::setConfig(config('database'));
    }

    // 获取 app 实例
    public function getContainer()
    {
        return new self();
    }

    // 获取 config 配置值
    public function getConfig($key)
    {
        return $this->config->get($key);
    }

    public function getPrinter()
    {
        return $this->printer;
    }

    public function getSignature()
    {
        return $this->app_signature;
    }

    public function printSignature()
    {
        $this->getPrinter()->display(sprintf("usage: %s", $this->getSignature()));
    }

    public function setSignature($app_signature)
    {
        $this->app_signature = $app_signature;
    }

    // 注册匿名函数方法
    public function registerCommand($name, $callable)
    {
        $this->command_registry->bind($name, $callable);
    }

    // 注册 controller 方法
    public function registerController($name, $controllerName)
    {
        $this->command_registry->bind($name, $controllerName);
    }

    // 总入口，执行命令
    public function runCommand(array $argv = [])
    {
        $input = new CommandCall($argv);
        
        try {
            $controller = $this->command_registry->getCallableController($input->command, $input->args);
            if ($controller instanceof CommandController) {
                $controller->boot($this, $input);
                call_user_func(array($controller, $input->subcommand), array($input->params));
                $controller->teardown();
                exit();
            }

            $this->runSingle($input);
        } catch (\Exception $e) {
            echo $e->getMessage() . PHP_EOL;
            exit();
        }
    }

    // 执行匿名函数方法
    private function runSingle($input)
    {
        try {
            $callable = $this->command_registry->getCallable($input->command);
            call_user_func($callable, $input);
        } catch (\Exception $e) {
            echo "ERROR: " . $e->getMessage();
        }
    }
}